#include <WifiText.h>
#include <crc/CRC16.h>

WifiTransfer* WifiTransfer::instance = nullptr;
static const char *key_uart_dev = "/dev/ttyS0";

WifiTransfer::WifiTransfer(/* args */)
{
}

WifiTransfer::~WifiTransfer()
{
}

WifiTransfer* WifiTransfer::getInstance() 
{
    if (instance == nullptr) {
        instance = new WifiTransfer();
    }
    return instance;
}


bool WifiTransfer::analyseCommBuffer(UartString* commBuffer)
{
    UString commString;
    uint8_t *buffer;
    uint8_t buf_len;
    uint8_t i = 0;
    uint8_t pos = 0;/* 实际payload长度 */
    WIFI_COMM_PACKAGE_T wifiCommPackage;

    if (commBuffer == nullptr) {
        return false;
    }

    do
    {
        i = 0, pos = 0;
        commString = commBuffer->getString();
        buffer = commString.data;
        buf_len = commString.length;
        if (buffer == nullptr || buf_len < WIFI_TYPE_FLAGS_LEN + 4) {
            return false;
        }

        /* 包头判断 */
        if (buffer[i++] != 0XF4 || buffer[i++] != 0XF5) {
            commBuffer->setStart(commBuffer->getStart() + 1);
            continue;
        }
        /* 获取包长度 */
        wifiCommPackage.len.H = buffer[i++];
        wifiCommPackage.len.L = buffer[i++];
        if (wifiCommPackage.len.getValue() < WIFI_TYPE_FLAGS_LEN || 
            wifiCommPackage.len.getValue() > WIFI_LENGTH_MAX_VALUE) {
            commBuffer->setStart(commBuffer->getStart() + i - 2);
            continue;
        }
        /* 获取设备类型 */
        wifiCommPackage.type.H = buffer[i++];
        wifiCommPackage.type.L = buffer[i++];
        if (false) {
            commBuffer->setStart(commBuffer->getStart() + i - 2);
            continue;
        }
        /* 获取cmd */
        wifiCommPackage.cmd = buffer[i++];
        /* 获取stat */
        wifiCommPackage.stat = buffer[i++];
        if (wifiCommPackage.stat != 0x01 && wifiCommPackage.stat != 0x02) {
            commBuffer->setStart(commBuffer->getStart() + i - 2);
            continue;
        }
        /* 获取flags */
        wifiCommPackage.flags.H = buffer[i++];
        wifiCommPackage.flags.L = buffer[i++];
        /* 获取payload */
        memset(wifiCommPackage.payload, 0, sizeof(wifiCommPackage.payload));
        for (int k = 0; k < wifiCommPackage.len.getValue() - WIFI_TYPE_FLAGS_LEN; k++) {
            if (buffer[i] == WIFI_COMM_HEADER_H) {
                /*  2 个 F4 表示一个 */
                if (buffer[i + 1] != buffer[i]) {
                    commBuffer->setStart(commBuffer->getStart() + i - 2);
                    continue;
                } else {
                    k++;i++;
                }
            }
            wifiCommPackage.payload[pos++] = buffer[i++];
        }
        /* 获取CRC */
        wifiCommPackage.crc.H = buffer[i++];
        wifiCommPackage.crc.L = buffer[i++];
        uint16_t crc16_value = CRC16::getInstance()->GetCRC16(buffer, i - 2);
        if (crc16_value != wifiCommPackage.crc.getValue()) {
            commBuffer->setStart(commBuffer->getStart() + i - 2);
            continue;
        }
    } while (false);
    
    SIGNWAY_LOGI("payload_type:%02X", wifiCommPackage.type.getValue());
    SIGNWAY_LOGI("payload_cmd = %02X", wifiCommPackage.cmd);
    SIGNWAY_LOGI("payload_stat = %02X", wifiCommPackage.stat);
    SIGNWAY_LOGI("payload_flags = %04X", wifiCommPackage.flags.getValue());
    SIGNWAY_LOGI("payload:");
    for (int i = 0; i < pos; i++) {
        printf("%#X ", wifiCommPackage.payload[i]);
    }
    SIGNWAY_LOGI(">>");

    return true;
}

size_t WifiTransfer::wifi_memcpy(void *dst, const void *src, size_t siz)
{
    register uint8_t *d = (uint8_t *)dst;
    register const uint8_t *s = (uint8_t *)src;
    register size_t n = siz;

    if (d == nullptr || s == nullptr || n == 0) {
        return -1;
    }

    /* Copy as many bytes as will fit */
    do {
        if (*s == 0XF4) {
            *d++ = *s;
        }
        if ((*d++ = *s++) == 0)
            break;
    } while (--n != 0);

    return d - (uint8_t *)dst;
}

bool WifiTransfer::transmitCommBuffer(void *buffer, int send_len)
{
    bool ret = false;
    int len = 0;
    uint8_t update = 0;
    uint8_t length = 0;
    uint8_t checksum_crcLo = 0;
    uint8_t checksum_crcHi = 0;
    uint16_t checksum_crc = 0;
    uint8_t send_buf[255] = {0};
    /* 5. 添加头部信息 */
    send_buf[length++] = WIFI_COMM_HEADER >> 8;
    send_buf[length++] = WIFI_COMM_HEADER & 0xFF;
    send_buf[length++] = ((send_len + 2) >> 8) & 0xFF;/* 包含CRC */
    send_buf[length++] = (send_len + 2) & 0xFF;/* 包含CRC */
    /* 6. 添加结构体内容 */
    memcpy(send_buf + length, (uint8_t *)buffer, send_len);
    length += send_len;
    /* 7. 添加尾部信息 */
    checksum_crc = CRC16::getInstance()->GetCRC16((uint8_t *)send_buf, length);
    checksum_crcHi = (checksum_crc & 0xFF00) >> 8;
    checksum_crcLo = (checksum_crc & 0xFF);
    send_buf[length++] = checksum_crcHi;
    send_buf[length++] = checksum_crcLo;
    /* 8. 发送send_buf */
    // len = wifiCommThread->xmitCommThreadUartBuffer(send_buf, length);

    printf(">>>:");
    for (size_t i = 0; i < length; i++)
    {
        printf("%#X ",send_buf[i]);
    }
    printf("\n");

    UartString *commBuffer = new UartString();
    commBuffer->addString(send_buf, length);
    analyseCommBuffer(commBuffer);
    
    if (len < 0)
        ret = false;
    else
        ret = true;
       
    return ret;
}

void WifiTransfer::wifiSendPacket(uint8_t cmd, uint8_t stat, UINT16_T flags, void *buffer, int send_len)
{
    bool ret = false;
    int len = 0;
    uint8_t update = 0;
    uint8_t length = 0;
    uint8_t checksum_crcLo = 0;
    uint8_t checksum_crcHi = 0;
    uint16_t checksum_crc = 0;
    uint8_t send_buf[255] = {0};

    send_buf[length++] = (WIFI_COMM_TYPE_ZKW >> 8) & 0xFF;
    send_buf[length++] = WIFI_COMM_TYPE_ZKW & 0xFF;
    send_buf[length++] = cmd;
    send_buf[length++] = stat;
    send_buf[length++] = flags.H;
    send_buf[length++] = flags.L;

    /* 6. 添加结构体内容 */
    send_len = wifi_memcpy(send_buf + length, (uint8_t *)buffer, send_len);
    length += send_len;
    transmitCommBuffer(send_buf, length);
}

/* send data periodcially*/
bool WifiTransfer::sendDataPeriodically(void)
{
    //TODO
}

void WifiTransfer::start(void)
{

}

void WifiTransfer::stop(void)
{

}

/* @brief: 打印数组内容-用于调试 */
void printArray(const void* array, const int len, const char* format = "%02X ", const char* title = "array:")
{
    const uint8_t* _array = (const uint8_t*) array;
    SIGNWAY_LOGI("%s", title);
    for (size_t i = 0; i < len; i++)
    {
        printf(format, _array[i]);
    }
    printf("\n");
}

class A {
public:
    A(int a) : a(a) {}
    int a;
};

class B : public A {
    B() : A(1) {

    }
};

void wifi_test()
{
    SIGNWAY_LOGI("systemStatus:             %02d", &(((WIFI_ZKW_STATUS*)0)->systemStatus));  /* 0/1/2 关机/待机/烹饪 */
    SIGNWAY_LOGI("workStatus:               %02d", &(((WIFI_ZKW_STATUS*)0)->workStatus));    /* 工作状态 */
    SIGNWAY_LOGI("stovetopLamps:            %02d", &(((WIFI_ZKW_STATUS*)0)->stovetopLamps)); /* 炉灯 0/1 关/开 */
    SIGNWAY_LOGI("waterTankActuators:       %02d", &(((WIFI_ZKW_STATUS*)0)->waterTankActuators)); /* 水箱推杆 0/1/2/3 关闭/停在中途/动作中/开启 */
    SIGNWAY_LOGI("workingMode:              %02d", &(((WIFI_ZKW_STATUS*)0)->workingMode)); /* 工作模式 */
    SIGNWAY_LOGI("cloudRecipesId:           %02d", &(((WIFI_ZKW_STATUS*)0)->cloudRecipesId)); /* 云菜谱ID */
    SIGNWAY_LOGI("modeAttributes:           %02d", &(((WIFI_ZKW_STATUS*)0)->modeAttributes)); /* 模式属性 */
    SIGNWAY_LOGI("fastWarmUp:               %02d", &(((WIFI_ZKW_STATUS*)0)->fastWarmUp));/* 快速预热 0/1 非/快速预热中 */
    SIGNWAY_LOGI("workTime:                 %02d", &(((WIFI_ZKW_STATUS*)0)->workTime)); /* 工作时间 */
    SIGNWAY_LOGI("resStartTime:             %02d", &(((WIFI_ZKW_STATUS*)0)->resStartTime)); /* 预约开始时间 */
    SIGNWAY_LOGI("remTime:                  %02d", &(((WIFI_ZKW_STATUS*)0)->remTime)); /* 工作剩余时间 */
    SIGNWAY_LOGI("remMultiPhase:            %02d", &(((WIFI_ZKW_STATUS*)0)->remMultiPhase)); /* 多段烹饪剩余时间 */
    SIGNWAY_LOGI("setUpTemp_1:              %02d", &(((WIFI_ZKW_STATUS*)0)->setUpTemp_1));/* 设定温度值 1 */
    SIGNWAY_LOGI("setUpTemp_2:              %02d", &(((WIFI_ZKW_STATUS*)0)->setUpTemp_2));/* 设定温度值 2（预留） */
    SIGNWAY_LOGI("tempSensors_1:            %02d", &(((WIFI_ZKW_STATUS*)0)->tempSensors_1)); /* 温度传感器 1 */
    SIGNWAY_LOGI("tempSensors_2:            %02d", &(((WIFI_ZKW_STATUS*)0)->tempSensors_2)); /* 温度传感器 2（预留） */
    SIGNWAY_LOGI("gatingStatus:             %02d", &(((WIFI_ZKW_STATUS*)0)->gatingStatus)); /* 门控状态 0/1 关/开 */
    SIGNWAY_LOGI("errorCode:                %02d", &(((WIFI_ZKW_STATUS*)0)->errorCode)); /* 故障号 */
    SIGNWAY_LOGI("waterShortage:            %02d", &(((WIFI_ZKW_STATUS*)0)->waterShortage)); /* 0：不缺水 1：缺水 */
    SIGNWAY_LOGI("waterTankLocation:        %02d", &(((WIFI_ZKW_STATUS*)0)->waterTankLocation)); /* 水箱位置 0/1 已推到位/未推到位 */
    SIGNWAY_LOGI("recipeRecordingStatus:    %02d", &(((WIFI_ZKW_STATUS*)0)->recipeRecordingStatus));/* 菜谱录制状态 */
    SIGNWAY_LOGI("recipePlaybackSteps:      %02d", &(((WIFI_ZKW_STATUS*)0)->recipePlaybackSteps)); /* 菜谱播放步骤 */
    SIGNWAY_LOGI("micDefFlipTip:            %02d", &(((WIFI_ZKW_STATUS*)0)->micDefFlipTip)); /* 微波解冻翻面提示 0/1 无/提示翻面 */
    SIGNWAY_LOGI("RESERVED:                 %02d", &(((WIFI_ZKW_STATUS*)0)->RESERVED[0]));/* 预留 */
    SIGNWAY_LOGI("RESERVED:                 %02d", &(((WIFI_ZKW_STATUS*)0)->RESERVED[1]));/* 预留 */

    SIGNWAY_LOGI("%d", sizeof(WIFI_ZKW_STATUS));

    WIFI_ZKW_STATUS wifiZkwStatus;
    uint8_t data[2];
    wifiZkwStatus.workingMode.L = 0xF5;
    wifiZkwStatus.workingMode.H = 0xF4;
    memcpy(data, &wifiZkwStatus.workingMode, sizeof(data));

    SIGNWAY_LOGI("%#X", data[0]);
    SIGNWAY_LOGI("%#X", data[1]);

    SIGNWAY_LOGI(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

    WifiTransfer *wifi = (WifiTransfer *)WifiTransfer::getInstance();
    wifi->wifiSendPacket(0XF1, 0X02, {.H = 0X12, .L = 0X34}, data, sizeof(data));
    SIGNWAY_LOGI(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

    WIFI_MAC_ADDR wifiMacAddr;
    int i = 0;
    wifiMacAddr.macAddress[i++] = i+1;
    wifiMacAddr.macAddress[i++] = i+1;
    wifiMacAddr.macAddress[i++] = i+1;
    wifiMacAddr.macAddress[i++] = i+1;
    wifiMacAddr.macAddress[i++] = i+1;
    wifiMacAddr.macAddress[i++] = i+1;
    SIGNWAY_LOGI("%s", wifiMacAddr.toString().c_str());

    struct {
        uint8_t station:1;
        uint8_t apmode:1;
        uint8_t esaylink:1;
    } wifiMode;

    memcpy(&wifiMode, data, sizeof(wifiMode));
    SIGNWAY_LOGI("data%#X", data[0]);
    SIGNWAY_LOGI("station %d", wifiMode.station);
    SIGNWAY_LOGI("apmode %d", wifiMode.apmode);
    SIGNWAY_LOGI("esaylink %d", wifiMode.esaylink);
}

union UINT16_T1 { 
    UINT16_T1(uint16_t value) : value(value) {}
    /* 大小端模式 */
    struct {
        uint8_t L;
        uint8_t H;
    };
    uint16_t value;
};

void uniontext()
{
    UINT16_T1 value = 0x1234;
    
    SIGNWAY_LOGI("%#X", value.H);
    SIGNWAY_LOGI("%#X", value.L);
}